/***
 * * PROJECT
 * *    Logical Neighborhoods - J2ME Run-Time Support 
 * * VERSION
 * *    $LastChangedRevision: 118 $
 * * DATE
 * *    $LastChangedDate: 2008-05-28 19:35:12 +0200 (Wed, 28 May 2008) $
 * * LAST_CHANGE_BY
 * *    $LastChangedBy: lmottola $
 * *
 * *    $Id: DatagramObjectIO.java 118 2008-05-28 17:35:12Z lmottola $
 * *
 * *   Logical Neighborhoods - 
 * *                   Programming Wireless Sensor Networks
 * *                   (One Slice at a Time)
 * *
 * *   This program is free software; you can redistribute it and/or
 * *   modify it under the terms of the GNU Lesser General Public License
 * *   as published by the Free Software Foundation; either version 2.1
 * *   of the License, or (at your option) any later version.
 * *
 * *   This program is distributed in the hope that it will be useful,
 * *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * *   GNU General Public License for more details.
 * *
 * *   You should have received a copy of the GNU Lesser General Public 
 * *   License along with this program; if not, you may find a copy at 
 * *   the FSF web site at 'www.gnu.org' or 'www.fsf.org', or you may 
 * *   write to the Free Software Foundation, Inc., 59 Temple 
 * *   Place - Suite 330, Boston, MA  02111-1307, USA
 ***/

package atag.runtime.ln;

import java.io.IOException;

import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;

import atag.runtime.ln.messages.LNMessage;

import com.sun.spot.io.j2me.radiogram.RadiogramConnection;
import java.io.DataInputStream;
import java.io.DataOutputStream;

/**
 * This class provides methods for sending and receiving objects using UDP
 * datagrams. Objects serialization is carried out using suitable
 * ByteInputStream and ByteOutputStream objects.
 * 
 * @author Luca Mottola <a
 *         href="mailto:mottola@elet.polimi.it">mottola@elet.polimi.it</a>
 * 
 */
public class RadioInterfaceIO implements Runnable, Interface {

	private boolean running;

	private DatagramConnection bcastConn;

	private DatagramConnection recvConn;

	private LNMessageListener receiver;

    private int interfaceId;

	/**
	 * Build a new object for sending and receiving objects via UDP datagrams.
	 * 
	 * @param port
	 *            the port at which we are going to receive UPD datagrams.
	 * @param bufferSize
	 *            the size of the receiver buffer.
	 * @param timeout
	 *            a timeout for receiving UDP datagrams.
	 */
	public RadioInterfaceIO(int port, LNMessageListener receiver, int interfaceId) {

		this.running = false;
		this.receiver = receiver;
        this.interfaceId = interfaceId;
		try {
			this.recvConn = (DatagramConnection) Connector.open("radiogram://:"
					+ port);
			this.bcastConn = (DatagramConnection) Connector
					.open("radiogram://broadcast:" + port);
			((RadiogramConnection) bcastConn).setMaxBroadcastHops(1);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void start() {
		running = true;
		new Thread(this).start();
	}

	/**
	 * Send an object to the Ipv4 local broadcast address. The receiver host has
	 * to wait for incoming objects at the same port as the local
	 * DatagramObjectIO object.
	 * 
	 * @param obj
	 *            the object that gets sent.
	 */
	public void sendBroadcastObject(LNMessage obj) {

		try {
			Datagram dg = bcastConn.newDatagram(bcastConn.getMaximumLength());
            dg = (Datagram)obj.serialize(dg);
			bcastConn.send(dg);

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Send the object o to the the specified Ipv4 address. The receiver host
	 * has to wait for incoming objects at the same port as the local
	 * DatagramObjectIO object.
	 * 
	 * @param obj
	 *            the objects that gets sent.
	 * @param hostAddress
	 *            the IPv4 address of the intended receiver.
	 */
	public void sendObject(LNMessage obj, String destination) {
		// TODO:
	}

	/**
	 * Receive an object at the local port specified at the creation of the
	 * object.
	 * 
	 * @return the object received.
	 */
	private LNMessage receiveObject() {

		Datagram recvDg = null;
		try {
			recvDg = recvConn.newDatagram(recvConn.getMaximumLength());
			recvConn.receive(recvDg);
			return LNMessage.deserialize(recvDg);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public void run() {
		while (running) {
			receiver.messageReceived(receiveObject(),this.interfaceId);
		}
	}

	public void stop() {
		running = false;
	}

}
